﻿using System.Net;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;

namespace PmSoft.Core.Extensions;

/// <summary>
/// HttpRequest 扩展方法
/// </summary>
public static class HttpRequestExtensions
{
	/// <summary>
	/// 从请求的 Authorization 头中提取 JWT Token。
	/// </summary>
	/// <param name="request">当前 HTTP 请求对象。</param>
	/// <returns>如果 Authorization 头存在且以 "Bearer " 开头，则返回 Token 字符串；否则返回 null。</returns>
	public static string? GetJwtToken(this HttpRequest request)
	{
		var authHeader = request.Headers["Authorization"].ToString();
		if (string.IsNullOrWhiteSpace(authHeader) || !authHeader.StartsWith("Bearer "))
			return null;

		return authHeader.Substring("Bearer ".Length).Trim();
	}

	/// <summary>
	/// 检查请求是否为 POST 请求
	/// </summary>
	/// <param name="request">要检查的请求</param>
	/// <returns>如果请求是 POST 请求，则为 true；否则为 false</returns>
	public static bool IsPostRequest(this HttpRequest request)
	{
		return request.Method.Equals(WebRequestMethods.Http.Post, StringComparison.InvariantCultureIgnoreCase);
	}

	/// <summary>
	/// 检查请求是否为 GET 请求
	/// </summary>
	/// <param name="request">要检查的请求</param>
	/// <returns>如果请求是 GET 请求，则为 true；否则为 false</returns>
	public static bool IsGetRequest(this HttpRequest request)
	{
		return request.Method.Equals(WebRequestMethods.Http.Get, StringComparison.InvariantCultureIgnoreCase);
	}

	/// <summary>
	/// 获取表单值
	/// </summary>
	/// <param name="request">请求</param>
	/// <param name="formKey">表单键</param>
	/// <returns>表示异步操作的任务，任务结果包含表单值</returns>
	public static async Task<StringValues> GetFormValueAsync(this HttpRequest request, string formKey)
	{
		if (!request.HasFormContentType)
			return new StringValues();

		var form = await request.ReadFormAsync();
		return form[formKey];
	}

	/// <summary>
	/// 检查表单中是否存在提供的键
	/// </summary>
	/// <param name="request">请求</param>
	/// <param name="formKey">表单键</param>
	/// <returns>表示异步操作的任务，任务结果包含键是否存在</returns>
	public static async Task<bool> IsFormKeyExistsAsync(this HttpRequest request, string formKey)
	{
		return await IsFormAnyAsync(request, key => key.Equals(formKey));
	}

	/// <summary>
	/// 检查表单中是否存在键
	/// </summary>
	/// <param name="request">请求</param>
	/// <param name="predicate">过滤器。如果不需要过滤则设置为 null</param>
	/// <returns>表示异步操作的任务，任务结果包含是否存在任何项</returns>
	public static async Task<bool> IsFormAnyAsync(this HttpRequest request, Func<string, bool> predicate = null)
	{
		if (!request.HasFormContentType)
			return false;

		var form = await request.ReadFormAsync();
		return predicate == null ? form.Any() : form.Keys.Any(predicate);
	}

	/// <summary>
	/// 获取与指定表单键关联的值
	/// </summary>
	/// <param name="request">请求</param>
	/// <param name="formKey">表单键</param>
	/// <returns>表示异步操作的任务，任务结果包含键是否存在及表单值</returns>
	public static async Task<(bool keyExists, StringValues formValue)> TryGetFormValueAsync(this HttpRequest request, string formKey)
	{
		if (!request.HasFormContentType)
			return (false, default);

		var form = await request.ReadFormAsync();
		var flag = form.TryGetValue(formKey, out var formValue);
		return (flag, formValue);
	}

	/// <summary>
	/// 返回 Form.Files 的第一个元素，如果序列不包含任何元素，则返回默认值
	/// </summary>
	/// <param name="request">请求</param>
	/// <returns>表示异步操作的任务，任务结果包含 <see cref="IFormFile"/> 元素或默认值</returns>
	public static async Task<IFormFile?> GetFirstOrDefaultFileAsync(this HttpRequest request)
	{
		if (!request.HasFormContentType)
			return default;

		var form = await request.ReadFormAsync();
		return form.Files.FirstOrDefault();
	}
}
